package agents;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import resource.Bid;
import resource.Tour;
import resource.TourItem;

import com.myprofile.profile.MuseumItem;
import com.myprofile.profile.ProfileType;

import daiia.ProfileManager;
import jade.content.ContentElement;
import jade.content.lang.Codec.CodecException;
import jade.content.lang.sl.SLCodec;
import jade.content.onto.OntologyException;
import jade.content.onto.UngroundedException;
import jade.content.onto.basic.Action;
import jade.content.onto.basic.Result;
import jade.core.AID;
import jade.core.Agent;
import jade.core.Location;
import jade.core.behaviours.FSMBehaviour;
import jade.core.behaviours.OneShotBehaviour;
import jade.core.behaviours.SequentialBehaviour;
import jade.core.behaviours.SimpleBehaviour;
import jade.domain.DFService;
import jade.domain.FIPAException;
import jade.domain.FIPANames;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.domain.FIPAAgentManagement.ServiceDescription;
import jade.domain.JADEAgentManagement.JADEManagementOntology;
import jade.domain.JADEAgentManagement.WhereIsAgentAction;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import jade.lang.acl.UnreadableException;

public class ProfilerAgent extends Agent {
	ProfileType profile;
	AID tourGuide;
	Tour tourToWalk;
	ArrayList<MuseumItem> visitedItems = new ArrayList<MuseumItem>();
	ArrayList<Tour> visitedTours = new ArrayList<Tour>();
	List<Tour> alreadySentTours = new ArrayList<Tour>();
	AID curator;
	AID parent;
	Location home;
	int numberOfClones = 0;

	protected void setup() {
		parent = getAID();
		home = here();
		init();
		String profileFileName = (String) this.getArguments()[0];
		profile = new ProfileManager().loadProfile(profileFileName);
		System.out.println(profile.getAge());
		String[] address = this.getAID().getAddressesArray();
		for (String a : address) {
			System.out.println(a);
		}
		addBehaviour(new BuyTourBehaviour());
	}

	private void init() {
		getContentManager().registerLanguage(new SLCodec(),
				FIPANames.ContentLanguage.FIPA_SL);
		getContentManager().registerOntology(
				JADEManagementOntology.getInstance());
	}

	private int getUtility(Bid b) {
		int P1 = b.P1 ? 1 : 0;
		int P2 = b.P2 ? 1 : 0;
		int price = (P1 * 10 + P2 * 25 + b.P3);
		if (b.tourType == Tour.T1) {
			return 10 - price;
		} else if (b.tourType == Tour.T2) {
			return 35 - price;
		} else {
			return 40 - price;
		}
	}

	@Override
	protected void afterClone() {
		super.afterClone();
		addBehaviour(new WalkTourBehaviour());
	}

	private class BuyTourBehaviour extends FSMBehaviour {
		private static final String FIND_TOUR_GUIDE = "a";
		private static final String SEND_TOUR_REQUEST = "b";
		private static final String LISTEN_FOR_PROPOSAL = "c";
		private static final String CALCULATE_COUNTER_PROPOSAL = "d";
		private static final String SEND_COUNTER_PROPOSAL = "e";
		private static final String SEND_ACCEPT_PROPOSAL_MESSAGE = "f";
		private static final String SEND_CANCEL_BID_MESSAGE = "g";
		private static final String SEND_PROFILE_MESSAGE = "h";
		private static final String LISTEN_FOR_TOUR = "i";
		private static final String CLONE_TO_CURATOR = "j";
		private static final String LISTEN_FOR_CLONE_ANSWER = "k";
		private static final String END_BUY_TOUR_BEHAVIOUR_BEHAVIOUR = "l";

		private static final int ACCEPT_PROPOSAL = 123;
		private static final int CANCEL_BIDING = 124;
		private static final int PROPOSAL_ACCEPTED = 125;
		private static final int DOUBLE_CANCEL = 126;
		private static final int PROPOSE_NEW_BID = 0;

		private int numberOfVisitedItems;
		private Bid currentBid;
		private Bid counterBid;
		private Bid finalBid;
		private ArrayList<Bid> bidStrategy = new ArrayList<Bid>();

		private boolean cancelBidMessageReceived = false;

		public BuyTourBehaviour() {
			registerFirstState(new FindTourGuideBehaviour(), FIND_TOUR_GUIDE);
			registerState(new SendTourRequestBehaviour(), SEND_TOUR_REQUEST);
			registerState(new ListenForProposalBehaviour(), LISTEN_FOR_PROPOSAL);
			registerState(new CalculateCounterProposalBehaviour(),
					CALCULATE_COUNTER_PROPOSAL);
			registerState(new SendCounterProposalBehaviour(),
					SEND_COUNTER_PROPOSAL);
			registerState(new AcceptProposalBehaviour(),
					SEND_ACCEPT_PROPOSAL_MESSAGE);
			registerState(new CancelBidBehaviour(), SEND_CANCEL_BID_MESSAGE);
			registerState(new SendProfileBehaviour(), SEND_PROFILE_MESSAGE);
			registerState(new ListenForTourBehaviour(), LISTEN_FOR_TOUR);
			registerState(new MoveToCuratorBehaviour(myAgent), CLONE_TO_CURATOR);
			registerState(new ListenForAnswerFromClone(),
					LISTEN_FOR_CLONE_ANSWER);
			registerLastState(new EndBuyTourBehaviourBehaviour(),
					END_BUY_TOUR_BEHAVIOUR_BEHAVIOUR);

			registerDefaultTransition(FIND_TOUR_GUIDE, SEND_TOUR_REQUEST);
			registerDefaultTransition(SEND_TOUR_REQUEST, LISTEN_FOR_PROPOSAL);
			registerDefaultTransition(LISTEN_FOR_PROPOSAL,
					CALCULATE_COUNTER_PROPOSAL);
			registerDefaultTransition(CALCULATE_COUNTER_PROPOSAL,
					SEND_COUNTER_PROPOSAL);
			registerDefaultTransition(SEND_COUNTER_PROPOSAL,
					LISTEN_FOR_PROPOSAL);
			registerDefaultTransition(SEND_CANCEL_BID_MESSAGE,
					LISTEN_FOR_PROPOSAL);
			registerDefaultTransition(SEND_PROFILE_MESSAGE, LISTEN_FOR_TOUR);
			registerDefaultTransition(LISTEN_FOR_TOUR, CLONE_TO_CURATOR);
			registerDefaultTransition(CLONE_TO_CURATOR, LISTEN_FOR_CLONE_ANSWER);
			registerDefaultTransition(LISTEN_FOR_CLONE_ANSWER,
					SEND_TOUR_REQUEST);
			registerDefaultTransition(SEND_ACCEPT_PROPOSAL_MESSAGE,
					SEND_PROFILE_MESSAGE);

			registerTransition(CALCULATE_COUNTER_PROPOSAL,
					SEND_ACCEPT_PROPOSAL_MESSAGE, ACCEPT_PROPOSAL);
			registerTransition(CALCULATE_COUNTER_PROPOSAL,
					SEND_CANCEL_BID_MESSAGE, CANCEL_BIDING);
			registerTransition(LISTEN_FOR_PROPOSAL, SEND_PROFILE_MESSAGE,
					PROPOSAL_ACCEPTED);
			registerTransition(SEND_CANCEL_BID_MESSAGE,
					END_BUY_TOUR_BEHAVIOUR_BEHAVIOUR, DOUBLE_CANCEL);
		}

		private void init() {
			numberOfVisitedItems = visitedTours.size() * 15;
			currentBid = null;
			counterBid = null;
			finalBid = null;
			bidStrategy = new ArrayList<Bid>();
			createBidStrategy();
			System.out.println("Initiated negotiation. Size of bid strategy: "
					+ bidStrategy.size());
		}

		private boolean visitedToursContainsTourType(int tourType) {
			for (Tour t : visitedTours) {
				if (t.equals(tourType))
					return true;
			}
			return false;
		}

		private void createBidStrategy() {

			if (!visitedToursContainsTourType(Tour.T1)) {
				bidStrategy.add(new Bid(true, false, 0, Tour.T1));
				bidStrategy.add(new Bid(false, true, 0, Tour.T1));
				bidStrategy.add(new Bid(true, true, 0, Tour.T1));
				bidStrategy.add(new Bid(false, false, numberOfVisitedItems
						- alreadySentTours.size(), Tour.T1));
				bidStrategy.add(new Bid(true, false, numberOfVisitedItems
						- alreadySentTours.size(), Tour.T1));
				bidStrategy.add(new Bid(false, true, numberOfVisitedItems
						- alreadySentTours.size(), Tour.T1));
				bidStrategy.add(new Bid(true, true, numberOfVisitedItems
						- alreadySentTours.size(), Tour.T1));
			}

			if (!visitedToursContainsTourType(Tour.T2)) {
				bidStrategy.add(new Bid(true, false, 0, Tour.T2));
				bidStrategy.add(new Bid(false, true, 0, Tour.T2));
				bidStrategy.add(new Bid(true, true, 0, Tour.T2));
				bidStrategy.add(new Bid(false, false, numberOfVisitedItems
						- alreadySentTours.size(), Tour.T2));
				bidStrategy.add(new Bid(true, false, numberOfVisitedItems
						- alreadySentTours.size(), Tour.T2));
				bidStrategy.add(new Bid(false, true, numberOfVisitedItems
						- alreadySentTours.size(), Tour.T2));
				bidStrategy.add(new Bid(true, true, numberOfVisitedItems
						- alreadySentTours.size(), Tour.T2));
			}

			if (!visitedToursContainsTourType(Tour.T3)) {
				bidStrategy.add(new Bid(true, false, 0, Tour.T3));
				bidStrategy.add(new Bid(false, true, 0, Tour.T3));
				bidStrategy.add(new Bid(true, true, 0, Tour.T3));
				bidStrategy.add(new Bid(false, false, numberOfVisitedItems
						- alreadySentTours.size(), Tour.T3));
				bidStrategy.add(new Bid(true, false, numberOfVisitedItems
						- alreadySentTours.size(), Tour.T3));
				bidStrategy.add(new Bid(false, true, numberOfVisitedItems
						- alreadySentTours.size(), Tour.T3));
				bidStrategy.add(new Bid(true, true, numberOfVisitedItems
						- alreadySentTours.size(), Tour.T3));
			}

			Collections.sort(bidStrategy, new BidComparator());
			for (Bid b : bidStrategy) {
				System.out.println("Utility: " + getUtility(b) + ", Bid: " + b);
			}
		}

		private Bid pop() {
			if (getUtility(bidStrategy.get(0)) >= 0) {
				Bid bid = bidStrategy.get(0);
				bidStrategy.remove(0);
				return bid;
			} else
				throw new RuntimeException("No more bids");
		}

		private class FindTourGuideBehaviour extends SimpleBehaviour {
			private boolean done = false;

			@Override
			public void action() {
				System.out.println("Search for tour guide");
				DFAgentDescription dfd = new DFAgentDescription();
				ServiceDescription sd = new ServiceDescription();
				sd.setName("tour");
				sd.setType("buy tour");
				dfd.addServices(sd);
				try {
					DFAgentDescription[] dfds = DFService.search(myAgent, dfd);
					if (dfds.length > 0) {
						tourGuide = dfds[0].getName();
						System.out.println("Found tour guide: "
								+ tourGuide.getLocalName());
						done = true;
					}
				} catch (FIPAException e) {
					e.printStackTrace();
				}
			}

			@Override
			public boolean done() {
				return done;
			}
		}

		private class SendTourRequestBehaviour extends OneShotBehaviour {

			@Override
			public void action() {
				init();
				System.out.println("Sends tour request");
				ACLMessage message = new ACLMessage(ACLMessage.REQUEST);
				message.addReceiver(tourGuide);
				message.setSender(myAgent.getAID());
				myAgent.send(message);
			}
		}

		private class ListenForProposalBehaviour extends SimpleBehaviour {

			boolean done = false;
			int onEnd;

			@Override
			public void action() {
				System.out.println("Listens for proposal from tour guide");
				ACLMessage message = myAgent.receive();
				if (message != null) {
					if (message.getPerformative() == ACLMessage.PROPOSE) {
						try {
							currentBid = (Bid) message.getContentObject();
							System.out.println("Received PROPOSE: "
									+ currentBid.P1 + " " + currentBid.P2 + " "
									+ currentBid.P3);
						} catch (UnreadableException e) {
							System.err.println("Not able obtain Bid object");
							e.printStackTrace();
						}
						onEnd = 0;
						done = true;
					} else if (message.getPerformative() == ACLMessage.ACCEPT_PROPOSAL) {
						System.out.println("Received ACCEPT_PROPOSAL");
						finalBid = counterBid;
						onEnd = PROPOSAL_ACCEPTED;
						done = true;
					} else if (message.getPerformative() == ACLMessage.CANCEL) {
						System.out.println("Received CANCEL");
						cancelBidMessageReceived = true;
						done = true;
					}
				} else
					block();
			}

			@Override
			public boolean done() {
				if (done) {
					done = false;
					return true;
				} else
					return done;
			}

			@Override
			public int onEnd() {
				return onEnd;
			}
		}

		private class CalculateCounterProposalBehaviour extends
				OneShotBehaviour {
			private int onEnd = 0;

			@Override
			public void action() {
				try {
					counterBid = pop();
					System.out.println("Calculates counter proposal. Utility: "
							+ getUtility(counterBid) + " "
							+ (getUtility(counterBid) < 0));
					if (getUtility(currentBid) == getUtility(counterBid)) {
						finalBid = currentBid;
						System.out.println("Accept proposal from tour guide");
						onEnd = ACCEPT_PROPOSAL;
					} else {
						System.out.println("Propose new bid");
						onEnd = PROPOSE_NEW_BID;
					}
				} catch (RuntimeException ex) {
					System.out.println("Calculates counter proposal. Utility: "
							+ getUtility(counterBid) + " "
							+ (getUtility(counterBid) < 0));
					if (getUtility(currentBid) == getUtility(counterBid)) {
						finalBid = currentBid;
						System.out.println("Accept proposal from tour guide");
						onEnd = ACCEPT_PROPOSAL;
					} else {
						System.out.println("CANCEL BIDING");
						onEnd = CANCEL_BIDING;
					}
				}
			}

			@Override
			public int onEnd() {
				int returnValue = onEnd;
				onEnd = 0;
				return returnValue;
			}
		}

		private class SendCounterProposalBehaviour extends OneShotBehaviour {

			@Override
			public void action() {
				System.out.println("Sends counter proposal");
				ACLMessage message = new ACLMessage(ACLMessage.PROPOSE);
				message.addReceiver(tourGuide);
				message.setSender(myAgent.getAID());
				try {
					System.out.println("Sending counter proposal: "
							+ counterBid);
					message.setContentObject(counterBid);
				} catch (IOException e) {
					System.err.println("Could not set content object");
					e.printStackTrace();
				}
				myAgent.send(message);
			}
		}

		private class AcceptProposalBehaviour extends OneShotBehaviour {

			@Override
			public void action() {
				System.out.println("Accept proposal");
				ACLMessage message = new ACLMessage(ACLMessage.ACCEPT_PROPOSAL);
				message.addReceiver(tourGuide);
				message.setSender(myAgent.getAID());
				myAgent.send(message);
			}
		}

		private class CancelBidBehaviour extends OneShotBehaviour {
			private int onEnd = 0;

			@Override
			public void action() {
				System.out.println("Cancel bid");
				ACLMessage message = new ACLMessage(ACLMessage.CANCEL);
				message.addReceiver(tourGuide);
				message.setSender(myAgent.getAID());
				myAgent.send(message);

				if (cancelBidMessageReceived)
					onEnd = DOUBLE_CANCEL;
			}

			@Override
			public int onEnd() {
				return onEnd;
			}
		}

		private class SendProfileBehaviour extends OneShotBehaviour {

			@Override
			public void action() {
				System.out.println("Send profile to tour guide");
				ProfileType profileToSend = new ProfileType();
				if (finalBid.P1) {
					profileToSend.setAge(profile.getAge());
					profileToSend.setAttitude(profile.getAttitude());
					profileToSend.setEducation(profile.getEducation());
					profileToSend.setMotivationOfVisit(profile
							.getMotivationOfVisit());
				}
				if (finalBid.P2) {
					profileToSend.setInterests(profile.getInterests());
				}
				if (finalBid.P3 > 0) {
					ProfileType.VisitedItems visitedItems = new ProfileType.VisitedItems();
					for (Tour t : visitedTours) {
						if (!alreadySentTours.contains(t)) {
							List<TourItem> items = t.getTourItems();
							for (TourItem item : items) {
								MuseumItem mi = new MuseumItem();
								mi.setId(item.getId());
								mi.setName(item.getName());
								mi.setRating(item.getRating());
								visitedItems.getVisitedItem().add(mi);
							}
							alreadySentTours.add(t);
						}
					}

					profileToSend.setVisitedItems(visitedItems);
				}
				ACLMessage message = new ACLMessage(ACLMessage.INFORM);
				message.addReceiver(tourGuide);
				message.setSender(myAgent.getAID());
				try {
					message.setContentObject(profileToSend);
				} catch (IOException e) {
					e.printStackTrace();
				}
				myAgent.send(message);
			}
		}

		private class ListenForTourBehaviour extends SimpleBehaviour {
			boolean done = false;

			@Override
			public void action() {
				System.out.println("Listen for tour from tour guide");
				ACLMessage message = myAgent.receive();
				if (message != null) {
					if (message.getPerformative() == ACLMessage.INFORM) {
						try {
							tourToWalk = (Tour) message.getContentObject();
							System.out.println("Tour"
									+ tourToWalk.getTourType()
									+ " received for " + finalBid.P1 + " "
									+ finalBid.P2 + " " + finalBid.P3);
						} catch (UnreadableException e) {
							System.err.println("Not able obtain Tour object");
							e.printStackTrace();
						}
						done = true;
					}
				} else
					block();
			}

			@Override
			public boolean done() {
				if (done) {
					done = false;
					return true;
				}
				return done;
			}
		}

		private class MoveToCuratorBehaviour extends OneShotBehaviour {

			private Location curatorLocation;
			private int numberOfClones = 0;

			public MoveToCuratorBehaviour(Agent agent) {
				super(agent);
			}

			@Override
			public void action() {
				SequentialBehaviour sb = new SequentialBehaviour();
				sb.addSubBehaviour(new SendQueryToAMSBehaviour());
				sb.addSubBehaviour(new ListenForAnswerBehaviour());
				sb.addSubBehaviour(new CloneAndMoveToCurator());
				addBehaviour(sb);
			}

			private class SendQueryToAMSBehaviour extends OneShotBehaviour {
				@Override
				public void action() {
					System.out.println("Sends request to AMS");
					WhereIsAgentAction wiaa = new WhereIsAgentAction();
					wiaa.setAgentIdentifier(tourToWalk.curator);
					Action action = new Action(myAgent.getAID(), wiaa);

					ACLMessage message = new ACLMessage(ACLMessage.REQUEST);
					message.addReceiver(myAgent.getAMS());
					message.setLanguage(FIPANames.ContentLanguage.FIPA_SL);
					message.setOntology(JADEManagementOntology.getInstance()
							.getName());

					try {
						myAgent.getContentManager()
								.fillContent(message, action);
					} catch (CodecException e) {
						e.printStackTrace();
					} catch (OntologyException e) {
						e.printStackTrace();
					}
					myAgent.send(message);
				}
			}

			private class ListenForAnswerBehaviour extends SimpleBehaviour {
				private boolean done = false;

				@Override
				public void action() {
					ACLMessage receivedMessage = myAgent
							.receive(MessageTemplate.MatchSender(myAgent
									.getAMS()));
					if (receivedMessage != null) {
						System.out.println("Received message from AMS");
						ContentElement content;
						try {
							content = myAgent.getContentManager()
									.extractContent(receivedMessage);
							Result result = (Result) content;
							curatorLocation = (Location) result.getValue();
							done = true;
						} catch (UngroundedException e) {
							e.printStackTrace();
						} catch (CodecException e) {
							e.printStackTrace();
						} catch (OntologyException e) {
							e.printStackTrace();
						}
					} else
						block();
				}

				@Override
				public boolean done() {
					return done;
				}
			}

			private class CloneAndMoveToCurator extends OneShotBehaviour {
				@Override
				public void action() {
					System.out.println("CLONE TO CURATOR");
					doClone(curatorLocation, myAgent.getLocalName() + "-clone"
							+ ++numberOfClones);
				}
			}

		}

		private class ListenForAnswerFromClone extends SimpleBehaviour {
			private boolean done = false;

			@SuppressWarnings("unchecked")
			@Override
			public void action() {
				ACLMessage message = receive(MessageTemplate
						.MatchPerformative(ACLMessage.CONFIRM));
				if (message != null) {
					try {
						System.out.println("INFORM FROM: "
								+ message.getSender().getLocalName());
						visitedItems = (ArrayList<MuseumItem>) message
								.getContentObject();
						List<TourItem> list = new ArrayList<TourItem>();
						for (MuseumItem item : visitedItems) {
							list.add(new TourItem(item.getId(), item.getName(),
									item.getRating()));
						}
						visitedTours.add(new Tour(list, finalBid.tourType));
						done = true;
					} catch (UnreadableException e) {
						e.printStackTrace();
					}
				} else
					block();
			}

			@Override
			public boolean done() {
				if (done) {
					done = false;
					return true;
				} else
					return done;
			}
		}

		private class EndBuyTourBehaviourBehaviour extends OneShotBehaviour {
			@Override
			public void action() {
				System.out.println("Negotiation completed");
				System.out.println("Number of items viewed: "
						+ visitedTours.size() * 15);
				for (MuseumItem item : visitedItems) {
					System.out.println("Adding " + item.getName());
					profile.getVisitedItems().getVisitedItem().add(item);
				}
				System.out.println("Dumping profile with "
						+ profile.getVisitedItems().getVisitedItem().size()
						+ " visited items");
				new ProfileManager().dumpProfile(profile,
						"data/" + myAgent.getLocalName() + "-after.xml");
			}
		}
	}

	private class WalkTourBehaviour extends FSMBehaviour {

		public WalkTourBehaviour() {
			registerFirstState(new RequestItemDetailBehaviour(), "1");
			registerState(new ListenForItemDetailBehaviour(), "2");
			registerState(new MoveBackBehaviour(), "3");
			registerLastState(new SendItemsToOriginalProfilerBehaviour(), "4");

			registerDefaultTransition("1", "2");
			registerDefaultTransition("2", "1");
			registerDefaultTransition("3", "4");

			registerTransition("1", "3", 1);
		}

		private class RequestItemDetailBehaviour extends OneShotBehaviour {
			private int onEnd = 0;

			@Override
			public void action() {
				System.out.println("HEJ");
				if (tourToWalk.getTourItems().size() > 0) {
					ACLMessage message = new ACLMessage(ACLMessage.REQUEST);
					message.addReceiver(tourToWalk.curator);
					message.setSender(myAgent.getAID());
					try {

						TourItem item = tourToWalk.getTourItems().get(0);
						tourToWalk.getTourItems().remove(0);
						message.setContentObject(item);
					} catch (IOException e) {
						e.printStackTrace();
					}
					myAgent.send(message);
				} else {
					onEnd = 1;
				}
			}

			@Override
			public int onEnd() {
				return onEnd;
			}
		}

		private class ListenForItemDetailBehaviour extends SimpleBehaviour {
			private boolean done = false;

			@Override
			public void action() {
				ACLMessage message = receive(MessageTemplate
						.MatchPerformative(ACLMessage.INFORM));
				if (message != null) {
					try {
						MuseumItem item = (MuseumItem) message
								.getContentObject();
						System.out.println(item.getName() + " "
								+ item.getMaterial());
						item.setRating(calculateRating(item));
						visitedItems.add(item);
						System.out.println(visitedItems.size()
								+ " items view so far");
						done = true;
					} catch (UnreadableException e) {
						e.printStackTrace();
					}
				} else
					block();
			}

			@Override
			public boolean done() {
				if (done) {
					done = false;
					return true;
				} else
					return done;
			}

			private float calculateRating(MuseumItem itemToRate) {
				float rate = 0;

				for (String interest : profile.getInterests().getInterest()) {
					if (itemToRate.getObjectType().contains(interest))
						rate++;
				}
				for (String interest : profile.getInterests().getInterest()) {
					if (itemToRate.getMaterial().contains(interest))
						rate++;
				}
				for (String interest : profile.getInterests().getInterest()) {
					if (itemToRate.getSubject().contains(interest))
						rate++;
				}
				return rate;
			}
		}

		private class MoveBackBehaviour extends OneShotBehaviour {
			@Override
			public void action() {
				doMove(home);
			}
		}

		private class SendItemsToOriginalProfilerBehaviour extends
				OneShotBehaviour {

			@Override
			public void action() {
				ACLMessage message = new ACLMessage(ACLMessage.CONFIRM);
				message.addReceiver(ProfilerAgent.this.parent);
				message.setSender(myAgent.getAID());
				try {
					message.setContentObject(visitedItems);
				} catch (IOException e) {
					e.printStackTrace();
				}
				myAgent.send(message);
			}
		}
	}

	public class BidComparator implements Comparator<Bid> {

		@Override
		public int compare(Bid b1, Bid b2) {
			int b1Utility = getUtility(b1);
			int b2Utility = getUtility(b2);

			if (b1Utility > b2Utility)
				return -1;
			else if (b1Utility < b2Utility)
				return 1;
			else {
				if (b1.tourType < b2.tourType)
					return 1;
				else
					return 0;
			}
		}
	}
}
